window_size=[1920,1080]  #窗口大小
mouse_pos=[960,540]  #鼠标位置
window_title=""  #被检测窗口名称
weights_path=""  #模型路径 请更改为你的模型存放位置 本模型缺陷很大 如有需求自行训练
data_path=""  #.yaml存放路径
window_name="test"
img_size=[320,320]  #以鼠标中心为中心的检测尺寸
stride=32
device=0
conf_thres=0.25  #置信度阈值
iou_thres=0.45  #极大值抑制阈值
classes=None
agnostic_nms=False
max_det=1000  #最大类别数目
line_thickness=3  #线框宽度
visualize=False
shot_size=img_size  #追踪框大小
hide_labels=True  #是否隐藏标签
hide_conf=True  #是否隐藏置信度
img_view=True  #是否开启预览框
head_track=True  #是否开启头部追踪  请勿同时开启头部追踪和身体追踪
body_track=False  #是否开启身体追踪
track =True  #是否自动追踪
auto_shoot=False  #是否开启自动射击
"""
可选模式表:
track body_track head_track
True  True       False      鼠标自动跟踪身体
True  False      True       鼠标自动跟踪头部
False True       False      鼠标不自动跟踪身体 但保存了最近身体坐标
False False      True       鼠标不自动跟踪头部 但保存了最近头部坐标
"""
"""
auto_shoot
True                        根据追踪模式自动射击
False                       不自动射击
"""
import logitech
import win32gui
from win32.lib.win32con import *
from ultralytics.utils.plotting import Annotator
from ultralytics.utils.plotting import colors
import pygetwindow as gw
import pyautogui
import numpy as np
import os
from pathlib import Path
import numpy as np
import torch
from models.common import DetectMultiBackend
from utils.augmentations import letterbox                           
from utils.general import (cv2, increment_path, non_max_suppression)
from utils.torch_utils import select_device
def is_mouse_captured_by_window(window_name: str) -> bool:
    """
    Returns True if the mouse is captured by the window with the given name.
    """
    window_handle = win32gui.FindWindow(None, window_name)
    if window_handle == 0:
        return False
    return window_handle == win32gui.GetCapture()
count=0
device=select_device(device)
model=DetectMultiBackend(weights_path,device=device,dnn=False,data=data_path,fp16=False)
names=model.names
model.warmup(imgsz=(1, 3, *shot_size))
while True:
    windwos =[]
    if window_title in gw.getAllTitles() :  #如果窗口存在且激活
        handle=win32gui.FindWindow(None,window_title)
        # 获取指定应用程序窗口
        #app_window = gw.getWindowsWithTitle(window_title)[0]  # 替换为你的应用程序标题

        # 获取窗口的位置和大小
        #waleft, top, width, height = app_window.left, app_window.top, app_window.width, app_window.height
        mouse_x,mouse_y=pyautogui.position()
        # 截取屏幕区域
        screenshot = pyautogui.screenshot(region=(int(mouse_pos[0]-shot_size[0]/2),int(mouse_pos[1]-shot_size[1]/2), shot_size[0], shot_size[1]))
        # 将截图转换为NumPy数组
        im = np.array(screenshot)  #RGB
        im0=im
        im = letterbox(im0, 
        img_size, stride, True)[0]  # padded resize 重设图片大小为32倍数
        im = im.transpose((2, 0, 1))  # HWC to CHW
        im = np.ascontiguousarray(im)  # contiguous
        im = torch.from_numpy(im).to(model.device)  #将numpy格式图片转为pytorch所支持的图片格式
        im = im.half() if model.fp16 else im.float()  # uint8 to fp16/32
        im /=255 #归一化
        if len(im.shape)==3:
            im=im[None]
        visualize = increment_path("" / Path("").stem, mkdir=True) if visualize else False
        pred = model(im, augment=False, visualize=visualize) #预测
        pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)  #极大值抑制
        for i,det in enumerate(pred):
            annotator=Annotator(im0,line_width=line_thickness,example=str(names))
            distance=999999999.0
            nearst_x=0
            nearst_y=0
            templist=[]
            for *xyxy,conf,cls in reversed(det):
                c=int(cls)
                label=names[c]
                mid_x=(xyxy[0].item()+xyxy[2].item())/2
                mid_y=(xyxy[1].item()+xyxy[3].item())/2
                templist.append((mid_x,mid_y,conf,cls))
                #print(xyxy[0],xyxy[1],xyxy[2],xyxy[3],conf,cls,"\n")
                if img_view:
                    c=int(cls)
                    label =None if hide_labels else (names[c] if hide_conf else f'{names[c]}{conf:.2f}')
                    annotator.box_label(xyxy,label,color=colors(c,True))
                if head_track and cls.item()==1:
                    temp_distance=pow(window_size[0]/2-shot_size[0]/2+mid_x-mouse_x,2)+pow(window_size[1]/2-shot_size[1]/2+mid_y-mouse_y,2)
                    if temp_distance<distance:
                        distance=temp_distance
                        nearst_x=mid_x
                        nearst_y=mid_y
                if body_track and cls.item()==0:
                    temp_distance=pow(window_size[0]/2-shot_size[0]/2+mid_x-mouse_x,2)+pow(window_size[1]/2-shot_size[1]/2+mid_y-mouse_y,2)
                    if temp_distance<distance:
                        distance=temp_distance
                        nearst_x=mid_x
                        nearst_y=mid_y
            if head_track or body_track:  #头部追踪 身体追踪
                if nearst_x !=0:
                    distance=9999999999.0
                    move_to_x=window_size[0]/2-shot_size[0]/2+nearst_x
                    move_to_y=window_size[1]/2-shot_size[1]/2+nearst_y
                    print("neareast:",move_to_x,move_to_y)
                    if track:
                        logitech.Logitech.mouse.move(int(move_to_x-mouse_pos[0]),int(move_to_y-mouse_pos[1]))
                else:
                    print("found target failed")
            if auto_shoot:  #自动射击)
                a=pow(window_size[0]/2-shot_size[0]/2+nearst_x-mouse_pos[0],2)+pow(window_size[1]/2-shot_size[1]/2+nearst_y-mouse_pos[1],2)
                print("a:",a)
                inrange=a<100
                print("inrange",inrange)
                if a <= 100:
                    logitech.Logitech.mouse.click(logitech.Logitech.mouse.press(1))
                    logitech.Logitech.mouse.release(logitech.Logitech.mouse.release(1))
                    print("shoot")
                    nearst_x=0
                    nearst_y=0
            if img_view:  #开启窗口预览
                im0=annotator.result()
                cv2.imshow(window_name,cv2.cvtColor(im0, cv2.COLOR_RGB2BGR))  #手动转换为RGB输出
                cv2.waitKey(1)

        # 显示截图
        #Image.fromarray(im0).show()
        count+=1
        print("第",count,"次循环")

    else:
        print("invalid window")





    # 保存截图为图片文件（可选）
    #screenshot.save("screenshot.png")
        # 在这里执行你想要执行的代码


